package com.novel.system.controller;

import com.novel.common.constants.Constants;
import com.novel.common.constants.UserConstants;
import com.novel.common.exception.business.BusinessException;
import com.novel.common.utils.StringUtils;
import com.novel.framework.annotation.Log;
import com.novel.framework.base.BaseController;
import com.novel.framework.enums.BusinessType;
import com.novel.framework.result.Result;
import com.novel.framework.shiro.utils.ShiroUtils;
import com.novel.framework.utils.excel.ExcelUtils;
import com.novel.framework.utils.spring.BeanUtils;
import com.novel.framework.validate.groups.AddGroup;
import com.novel.framework.validate.groups.EditGroup;
import com.novel.framework.web.page.TableDataInfo;
import com.novel.system.domain.SysUser;
import com.novel.system.domain.vo.SysUserVo;
import com.novel.system.service.SysPostService;
import com.novel.system.service.SysRoleService;
import com.novel.system.service.SysUserService;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 用户操作控制器
 *
 * @author novel
 * @date 2020/3/2
 */
@RestController
@RequestMapping("/system/user")
public class SysUserController extends BaseController {
    private final SysUserService sysUserService;
    private final SysRoleService roleService;
    private final SysPostService postService;

    public SysUserController(SysUserService sysUserService, SysRoleService roleService, SysPostService postService) {
        this.sysUserService = sysUserService;
        this.roleService = roleService;
        this.postService = postService;
    }

    /**
     * 添加用户信息
     *
     * @param user 用户信息
     * @return 操作结果
     */
    @Log(title = "用户管理", businessType = BusinessType.INSERT)
    @RequiresPermissions("system:user:add")
    @PostMapping("/add")
    public Result addSave(@Validated(AddGroup.class) SysUser user) {
        if (UserConstants.USER_NAME_NOT_UNIQUE.equals(sysUserService.checkUserNameUnique(user))) {
            throw new BusinessException("新增用户'" + user.getUserName() + "'失败，登录账号已存在");
        } else if (UserConstants.USER_PHONE_NOT_UNIQUE.equals(sysUserService.checkPhoneUnique(user))) {
            throw new BusinessException("新增用户'" + user.getUserName() + "'失败，手机号码已存在");
        } else if (UserConstants.USER_EMAIL_NOT_UNIQUE.equals(sysUserService.checkEmailUnique(user))) {
            throw new BusinessException("新增用户'" + user.getUserName() + "'失败，邮箱账号已存在");
        }

        user.setCreateBy(ShiroUtils.getUserName());
        user.setPassword(Constants.DEFAULT_PASSWORD);
        return toAjax(sysUserService.insertUser(user), "用户新增成功", "用户新增失败");
    }

    /**
     * 删除用户信息
     *
     * @param ids 用户ID
     * @return 操作结果
     */
    @Log(title = "用户管理", businessType = BusinessType.DELETE)
    @RequiresPermissions("system:user:remove")
    @DeleteMapping("/remove")
    public Result remove(Long[] ids) {
        if (ids != null) {
            for (Long id : ids) {
                SysUser user = sysUserService.selectUserById(id);
                ShiroUtils.logoutUsersByUserName(user.getUserName());
            }
        }
        return toAjax(sysUserService.deleteUserByIds(ids), "用户删除成功", "用户删除失败");
    }

    /**
     * 保存编辑用户信息
     *
     * @param user 用户信息
     * @return 操作结果
     */
    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
    @RequiresPermissions("system:user:edit")
    @PutMapping("/edit")
    public Result editSave(@Validated(EditGroup.class) SysUser user) {
        if (StringUtils.isNotNull(user.getId()) && SysUser.isAdmin(user.getId())) {
            throw new BusinessException("不允许修改超级管理员用户");
        }
        if (UserConstants.USER_PHONE_NOT_UNIQUE.equals(sysUserService.checkPhoneUnique(user))) {
            throw new BusinessException("新增用户'" + user.getUserName() + "'失败，手机号码已存在");
        } else if (UserConstants.USER_EMAIL_NOT_UNIQUE.equals(sysUserService.checkEmailUnique(user))) {
            throw new BusinessException("新增用户'" + user.getUserName() + "'失败，邮箱账号已存在");
        }
        user.setUpdateBy(ShiroUtils.getUserName());
        return toAjax(sysUserService.updateUser(user), "用户修改成功！", "用户修改失败");
    }

    /**
     * 查询用户列表
     *
     * @param user 查询条件
     * @return 用户列表
     */
    @RequiresPermissions("system:user:list")
    @GetMapping("/list")
    public TableDataInfo list(SysUser user) {
        startPage();
        List<SysUser> userList = sysUserService.selectUserList(user);
        return getDataTable(userList);
    }

    /**
     * 获取用户所拥有的角色
     *
     * @param id 用户id
     * @return 操作结果
     */
    @RequiresPermissions("system:user:edit")
    @GetMapping("/getUserRole")
    @Validated
    public Result getUserRole(@NotNull(message = "用户ID不能为空") @Min(value = 1, message = "用户ID必须大于0") Long id) {
        Map<String, Object> map = roleService.selectRolesByUserId(id);
        return Result.success(map);
    }

    /**
     * 获取用户所拥有的岗位
     *
     * @param id 用户id
     * @return 操作结果
     */
    @RequiresPermissions("system:user:edit")
    @GetMapping("/getUserPost")
    @Validated
    public Result getUserPost(@NotNull(message = "用户ID不能为空") @Min(value = 1, message = "用户ID必须大于0") Long id) {
        Map<String, Object> map = postService.selectPostsByUserId(id);
        return Result.success(map);
    }

    /**
     * 根据用户id查询岗位信息
     */
//    @RequiresPermissions("system:user:list")
    @GetMapping("/getPostListByUserId/{id}")
    @Validated
    public Result getPostListByUserId(@PathVariable("id") @NotNull(message = "用户ID不能为空") @Min(value = 1, message = "用户ID必须大于0") Long id) {
        return toAjax(postService.selectPostListByUserId(id));
    }


    /**
     * 重置密码
     *
     * @param userId 用户id
     * @return 结果
     */
    @Log(title = "重置密码", businessType = BusinessType.UPDATE)
    @RequiresPermissions("system:user:edit")
    @PutMapping("/resetPwd/{id}")
    public Result resetPwd(@PathVariable("id") @NotNull(message = "用户ID不能为空") @Min(value = 1, message = "用户ID必须大于0") Long userId) {
        if (StringUtils.isNotNull(userId) && SysUser.isAdmin(userId)) {
            throw new BusinessException("不允许修改超级管理员用户");
        }
        if (sysUserService.resetUserPwd(userId, Constants.DEFAULT_PASSWORD)) {
            SysUser user = sysUserService.selectUserById(userId);
            ShiroUtils.logoutUsersByUserName(user.getUserName());
            return success("密码设置成功");
        }
        return error("密码设置成功");
    }


    /**
     * 校验用户名
     *
     * @return 结果
     */
    @PostMapping("/checkUserNameUnique")
    public Result checkUserNameUnique(SysUser user) {
        return toAjax(sysUserService.checkUserNameUnique(user));
    }

    /**
     * 校验手机号码
     *
     * @return 结果
     */
    @PostMapping("/checkPhoneUnique")
    public Result checkPhoneUnique(SysUser user) {
        return toAjax(sysUserService.checkPhoneUnique(user));
    }

    /**
     * 校验email邮箱
     *
     * @return 结果
     */
    @PostMapping("/checkEmailUnique")
    public Result checkEmailUnique(SysUser user) {
        return toAjax(sysUserService.checkEmailUnique(user));
    }


    /**
     * 导出excel
     *
     * @param user 查询信息
     * @return 结果
     */
    @Log(title = "用户管理", businessType = BusinessType.EXPORT)
    @RequiresPermissions("system:user:export")
    @GetMapping("/export")
    public Result export(SysUser user) {
        startPage();
        List<SysUser> userList = sysUserService.selectUserList(user);
        String fileName = ExcelUtils.exportExcelToFile(userList, "用户信息", SysUser.class);
        Map<String, Object> map = new HashMap<>(1);
        map.put("fileName", fileName);
        return toAjax(map);
    }

    /**
     * 导入excel
     *
     * @return 结果
     */
    @Log(title = "用户管理", businessType = BusinessType.IMPORT)
    @RequiresPermissions("system:user:import")
    @PostMapping("/import")
    public Result importUser(@RequestParam("file") MultipartFile file) throws IOException {
        List<SysUserVo> personVoList = ExcelUtils.importExcel(file, 1, 1, true, SysUserVo.class);
        List<SysUser> list = new ArrayList<>(personVoList.size());
        for (SysUserVo sysUserVo : personVoList) {
            SysUser sysUser = new SysUser();
            BeanUtils.copyProperties(sysUserVo, sysUser);
            list.add(sysUser);
        }
        return toAjax(sysUserService.insertUser(list));
    }

    /**
     * 数据导入模板
     *
     * @return 导入模板
     */
    @RequiresPermissions("system:user:import")
    @GetMapping("/importTemplate")
    public Result importTemplate() {
        String fileName = ExcelUtils.exportExcelToFile(new ArrayList<SysUserVo>(), "用户导入模板", SysUserVo.class);
        Map<String, Object> map = new HashMap<>(1);
        map.put("fileName", fileName);
        return toAjax(map);
    }

}
